hvm: Do not save/restore shared_info gpfn location.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 19 Mar 2007 16:48:24 +0000 (16:48 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 19 Mar 2007 16:48:24 +0000 (16:48 +0000)
Instead of kludging a max_gpfn estimate in shared_info, add a new
XENMEM command to discover the actual maximum gpfn value as known by
the shadow code.

This needs to be more robust when we support HVM ballooning in future
anyway. One interesting point is that max_gpfn may be close to 4GB
even for small-memory HVM guests since for example SVGA LFB is mapped
into the I/O hole. We may need to special case the I/O hole somehow,
or provide some finer-grained way to find out which parts of the GPFN
space are actually used (e.g., get Xen to fill in a bitmap with 1 bit
per 1024 pages, or similar).

Signed-off-by: Keir Fraser <keir@xensource.com>
13 files changed:
tools/libxc/xc_core_x86.c
tools/libxc/xc_hvm_build.c
tools/libxc/xc_hvm_restore.c
tools/libxc/xc_hvm_save.c
tools/libxc/xc_private.c
xen/arch/x86/mm.c
xen/arch/x86/mm/shadow/common.c
xen/common/compat/memory.c
xen/common/memory.c
xen/include/asm-ia64/mm.h
xen/include/asm-powerpc/mm.h
xen/include/asm-x86/mm.h
xen/include/public/memory.h

index 6ea775aef60ff9152f8faf6262b062bc0090c10c..bd821107136ff32d49a830772ce27af27f1e57e8 100644 (file)
 #include "xg_private.h"
 #include "xc_core.h"
 
+static int max_gpfn(int xc_handle, domid_t domid)
+{
+    return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
+}
+
 int
 xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
 {
-    if ( info->hvm )
-        return 1;
-    return 0;
+    return info->hvm;
 }
 
 int
@@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
                             xc_core_memory_map_t **mapp,
                             unsigned int *nr_entries)
 {
-    unsigned long max_pfn = live_shinfo->arch.max_pfn;
-    xc_core_memory_map_t *map = NULL;
+    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
+    xc_core_memory_map_t *map;
 
     map = malloc(sizeof(*map));
-    if ( !map )
+    if ( map == NULL )
     {
         PERROR("Could not allocate memory");
-        goto out;
+        return -1;
     }
 
     map->addr = 0;
@@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info,
     *mapp = map;
     *nr_entries = 1;
     return 0;
-
-out:
-    if ( map )
-        free(map);
-    return -1;
 }
 
 int
@@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info,
     xen_pfn_t *live_p2m_frame_list_list = NULL;
     xen_pfn_t *live_p2m_frame_list = NULL;
     uint32_t dom = info->domid;
-    unsigned long max_pfn = live_shinfo->arch.max_pfn;
+    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
     int ret = -1;
     int err;
 
index 4b23e9fdb11fa8120cbf15841f834ec8f73b4527..751aa9cf7a860db918c357327675f1aef98e6d48 100644 (file)
@@ -286,7 +286,6 @@ static int setup_guest(int xc_handle,
     /* NB. evtchn_upcall_mask is unused: leave as zero. */
     memset(&shared_info->evtchn_mask[0], 0xff,
            sizeof(shared_info->evtchn_mask));
-    shared_info->arch.max_pfn = page_array[nr_pages - 1];
     munmap(shared_info, PAGE_SIZE);
 
     if ( v_end > HVM_BELOW_4G_RAM_END )
index 0dafa82874c50044f97d0a3a0cf7d2f6d3650c40..4b54b0aaf50be2b4de5ee2da062d5cb860210ef4 100644 (file)
@@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
 {
     DECLARE_DOMCTL;
 
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-
     /* A copy of the CPU context of the guest. */
     vcpu_guest_context_t ctxt;
 
@@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
     uint8_t *hvm_buf = NULL;
     unsigned long long v_end, memsize;
     unsigned long shared_page_nr;
-    shared_info_t *shared_info = NULL;
-    xen_pfn_t arch_max_pfn;
 
     unsigned long pfn;
     unsigned int prev_pc, this_pc;
@@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
     /* Types of the pfns in the current region */
     unsigned long region_pfn_type[MAX_BATCH_SIZE];
 
-    struct xen_add_to_physmap xatp;
-
     /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
     unsigned long nr_pages;
 
@@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
         pfns[i] = i;
     for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
         pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
-    arch_max_pfn = pfns[max_pfn];/* used later */
 
     /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
     rc = xc_domain_memory_populate_physmap(
@@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io_fd,
         goto out;
     }
 
-    /* Shared-info pfn */
-    if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
-        ERROR("reading the shared-info pfn failed!\n");
-        goto out;
-    }
-    /* Map the shared-info frame where it was before */
-    xatp.domid = dom;
-    xatp.space = XENMAPSPACE_shared_info;
-    xatp.idx   = 0;
-    xatp.gpfn  = shared_info_frame;
-    if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) {
-        ERROR("setting the shared-info pfn failed!\n");
-        goto out;
-    }
-    if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) ||
-         ((shared_info = xc_map_foreign_range(
-             xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
-             shared_info_frame)) == NULL) )
-        goto out;
-    /* shared_info.arch.max_pfn is used by dump-core */
-    shared_info->arch.max_pfn = arch_max_pfn;
-    munmap(shared_info, PAGE_SIZE);
-
     rc = 0;
     goto out;
 
index 54a3897ce555e9b43edab2851f095f2e1cb9b07e..75a017cf7c080e0194972b65800d1f3c2d4aa642 100644 (file)
@@ -302,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
     /* The size of an array big enough to contain all guest pfns */
     unsigned long pfn_array_size;
 
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-
     /* Other magic frames: ioreqs and xenstore comms */
     unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
 
@@ -318,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
     uint32_t hvm_buf_size;
     uint8_t *hvm_buf = NULL;
 
-    /* Live mapping of shared info structure */
-    shared_info_t *live_shinfo = NULL;
-
     /* base of the region in which domain memory is mapped */
     unsigned char *region_base = NULL;
 
@@ -372,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
         ERROR("HVM:Could not get vcpu context");
         goto out;
     }
-    shared_info_frame = info.shared_info_frame;
 
     /* cheesy sanity check */
     if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
@@ -381,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
         goto out;
     }
 
-    /* Map the shared info frame */
-    if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
-                                            PROT_READ, shared_info_frame))) {
-        ERROR("HVM:Couldn't map live_shinfo");
-        goto out;
-    }
-
     if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
          || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
          || xc_get_hvm_param(xc_handle, dom, 
@@ -525,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
 
         DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
 
-        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
-            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
-                    max_pfn, live_shinfo->arch.max_pfn);
-            ERROR("Max pfn doesn't match shared info");
-            goto out;
-        }
-
         while( N < pfn_array_size ){
 
             unsigned int this_pc = (N * 100) / pfn_array_size;
@@ -679,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                     goto out;
                 }
 
-                DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
-                        info.shared_info_frame,
+                DPRINTF("SUSPEND eip %08lx edx %08lx\n",
                         (unsigned long)ctxt.user_regs.eip,
                         (unsigned long)ctxt.user_regs.edx);
             }
@@ -768,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
         ERROR("write HVM info failed!\n");
     }
 
-    /* Shared-info pfn */
-    if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
-        ERROR("write shared-info pfn failed!\n");
-        goto out;
-    }
     /* Success! */
     rc = 0;
 
index 3816b0a83b2b4de40bdb6694063311ba420d13ae..3e2557e581b827ea3b419247654c8768772698cd 100644 (file)
@@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle,
             goto out1;
         }
         break;
+    case XENMEM_current_reservation:
+    case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
+        if ( lock_pages(arg, sizeof(domid_t)) )
+        {
+            PERROR("Could not lock");
+            goto out1;
+        }
+        break;
     }
 
     ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle,
     case XENMEM_add_to_physmap:
         unlock_pages(arg, sizeof(struct xen_add_to_physmap));
         break;
+    case XENMEM_current_reservation:
+    case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
+        unlock_pages(arg, sizeof(domid_t));
+        break;
     }
 
  out1:
index 1c65070d15ada301260d764feabf8c3c7f3234f8..e0590f33a2a84234dce5fd2a833d79b98023a6aa 100644 (file)
 #include <asm/x86_emulate.h>
 #include <asm/e820.h>
 #include <asm/hypercall.h>
+#include <asm/shared.h>
 #include <public/memory.h>
 
 #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p)
     return 0;
 }
 
+unsigned long domain_get_maximum_gpfn(struct domain *d)
+{
+    return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d);
+}
+
 void share_xen_page_with_guest(
     struct page_info *page, struct domain *d, int readonly)
 {
index 15ebf1d541eb0887bf30c8fd61c5896eedc2027e..efabba8223e3119a0edf314091296417b093c711 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/current.h>
 #include <asm/flushtlb.h>
 #include <asm/shadow.h>
-#include <asm/shared.h>
 #include "private.h"
 
 
@@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
 {
     ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL);
     d->arch.paging.shadow.dirty_bitmap_size =
-        (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) &
+        (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) &
         ~(BITS_PER_LONG - 1);
     d->arch.paging.shadow.dirty_bitmap =
         xmalloc_array(unsigned long,
@@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain *d)
         d->arch.paging.shadow.dirty_bitmap_size = 0;
         return -ENOMEM;
     }
-    memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8);
+    memset(d->arch.paging.shadow.dirty_bitmap, 0,
+           d->arch.paging.shadow.dirty_bitmap_size/8);
 
     return 0;
 }
index 1301e42f0416a8a47adb619bfb207dd040260b40..53628d7a35638a21e1aa1e9e11570ba0aa0b6a31 100644 (file)
@@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
 
         case XENMEM_current_reservation:
         case XENMEM_maximum_reservation:
+        case XENMEM_maximum_gpfn:
         {
 #define xen_domid_t domid_t
 #define compat_domid_t domid_compat_t
@@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat)
         case XENMEM_maximum_ram_page:
         case XENMEM_current_reservation:
         case XENMEM_maximum_reservation:
+        case XENMEM_maximum_gpfn:
             break;
 
         case XENMEM_translate_gpfn_list:
index f7e5efc0a53ab7a06bdcb77c5f47bc895d44273c..edd2ebe8d511ec8541c13bdbe687cf9914dca6da 100644 (file)
@@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
 
     case XENMEM_current_reservation:
     case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
         if ( copy_from_guest(&domid, arg, 1) )
             return -EFAULT;
 
@@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
         else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
             return -ESRCH;
 
-        rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages;
+        switch ( op )
+        {
+        case XENMEM_current_reservation:
+            rc = d->tot_pages;
+            break;
+        case XENMEM_maximum_reservation:
+            rc = d->max_pages;
+            break;
+        default:
+            ASSERT(op == XENMEM_maximum_gpfn);
+            rc = domain_get_maximum_gpfn(d);
+            break;
+        }
 
         if ( unlikely(domid != DOMID_SELF) )
             rcu_unlock_domain(d);
index fa0830d41435f1faeb57f83a69280a7d07432211..057f841c161da84d5ad6d77b214a22033ef2baef 100644 (file)
@@ -511,4 +511,6 @@ int steal_page(
 
 #define domain_clamp_alloc_bitsize(d, b) (b)
 
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
 #endif /* __ASM_IA64_MM_H__ */
index e258d5eb1b5853c81a98df19b0e6bfe01c44f994..ed6a10c67bfb080b8d8de9b1e391d18f6e1b20af 100644 (file)
@@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, struct page_info *page,
 
 #define domain_clamp_alloc_bitsize(d, b) (b)
 
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
 #endif
index b240e4b5ca1acfec39d84e40133d9b8fbb543f32..225605efd4fcc5ff6d0415252ad03111c23dcae4 100644 (file)
@@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
 # define domain_clamp_alloc_bitsize(d, b) (b)
 #endif
 
+unsigned long domain_get_maximum_gpfn(struct domain *d);
 
 #endif /* __ASM_X86_MM_H__ */
index 97a6bbfea2461fc8a49bf6d1d81b094ed4c19243..7b1ef44d32ca5ef87a7360f5fb44917f2daaccd9 100644 (file)
@@ -128,6 +128,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
 #define XENMEM_current_reservation  3
 #define XENMEM_maximum_reservation  4
 
+/*
+ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
+ */
+#define XENMEM_maximum_gpfn         14
+
 /*
  * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
  * mapping table. Architectures which do not have a m2p table do not implement